﻿///查看fps和debug的内容
using UnityEngine;

using System.Collections.Generic;

using System;

using UnityEngine.Profiling;
namespace FrameWorkSong
{
    public class Debugger : MonoBehaviour

    {

        /// <summary>

        /// 是否允许调试

        /// </summary>

        public bool AllowDebugging = true;

        private DebugType _debugType = DebugType.Console;

        private List<LogData> _logInformations = new List<LogData>();

        private int _currentLogIndex = -1;

        private int _infoLogCount = 0;

        private int _warningLogCount = 0;

        private int _errorLogCount = 0;

        private int _fatalLogCount = 0;

        private bool _showInfoLog = true;

        private bool _showWarningLog = true;

        private bool _showErrorLog = true;

        private bool _showFatalLog = true;

        private Vector2 _scrollLogView = Vector2.zero;

        private Vector2 _scrollCurrentLogView = Vector2.zero;

        private Vector2 _scrollSystemView = Vector2.zero;

        private bool _expansion = false;

        private Rect _windowRect = new Rect(0, 0, 100, 60);

        private int _fps = 0;

        private Color _fpsColor = Color.white;

        private int _frameNumber = 0;

        private float _lastShowFPSTime = 0f;

        private void Start()

        {

            if (AllowDebugging)

            {

                Application.logMessageReceived += LogHandler;

            }

        }

        private void Update()

        {

            if (AllowDebugging)

            {

                _frameNumber += 1;

                float time = Time.realtimeSinceStartup - _lastShowFPSTime;

                if (time >= 1)

                {

                    _fps = (int)(_frameNumber / time);

                    _frameNumber = 0;

                    _lastShowFPSTime = Time.realtimeSinceStartup;

                }

            }

        }

        private void OnDestory()

        {

            if (AllowDebugging)

            {

                Application.logMessageReceived -= LogHandler;

            }

        }

        private void LogHandler(string condition, string stackTrace, LogType type)

        {

            LogData log = new LogData();

            log.time = DateTime.Now.ToString("HH:mm:ss");

            log.message = condition;

            log.stackTrace = stackTrace;

            if (type == LogType.Assert)

            {

                log.type = "Fatal";

                _fatalLogCount += 1;

            }

            else if (type == LogType.Exception || type == LogType.Error)

            {

                log.type = "Error";

                _errorLogCount += 1;

            }

            else if (type == LogType.Warning)

            {

                log.type = "Warning";

                _warningLogCount += 1;

            }

            else if (type == LogType.Log)

            {

                log.type = "Info";

                _infoLogCount += 1;

            }

            _logInformations.Add(log);

            if (_warningLogCount > 0)

            {

                _fpsColor = Color.yellow;

            }

            if (_errorLogCount > 0)

            {

                _fpsColor = Color.red;

            }

        }

        private void OnGUI()

        {

            if (AllowDebugging)

            {

                if (_expansion)

                {

                    _windowRect = GUI.Window(0, _windowRect, ExpansionGUIWindow, "DEBUGGER");

                }

                else

                {

                    _windowRect = GUI.Window(0, _windowRect, ShrinkGUIWindow, "DEBUGGER");

                }

            }

        }

        private void ExpansionGUIWindow(int windowId)

        {

            GUI.DragWindow(new Rect(0, 0, 10000, 20));

            #region title

            GUILayout.BeginHorizontal();

            GUI.contentColor = _fpsColor;

            if (GUILayout.Button("FPS:" + _fps, GUILayout.Height(30)))

            {

                _expansion = false;

                _windowRect.width = 100;

                _windowRect.height = 60;

            }

            GUI.contentColor = (_debugType == DebugType.Console ? Color.white : Color.gray);

            if (GUILayout.Button("Console", GUILayout.Height(30)))

            {

                _debugType = DebugType.Console;

            }

            GUI.contentColor = (_debugType == DebugType.Memory ? Color.white : Color.gray);

            if (GUILayout.Button("Memory", GUILayout.Height(30)))

            {

                _debugType = DebugType.Memory;

            }

            GUI.contentColor = (_debugType == DebugType.System ? Color.white : Color.gray);

            if (GUILayout.Button("System", GUILayout.Height(30)))

            {

                _debugType = DebugType.System;

            }

            GUI.contentColor = (_debugType == DebugType.Screen ? Color.white : Color.gray);

            if (GUILayout.Button("Screen", GUILayout.Height(30)))

            {

                _debugType = DebugType.Screen;

            }

            GUI.contentColor = (_debugType == DebugType.Quality ? Color.white : Color.gray);

            if (GUILayout.Button("Quality", GUILayout.Height(30)))

            {

                _debugType = DebugType.Quality;

            }

            GUI.contentColor = (_debugType == DebugType.Environment ? Color.white : Color.gray);

            if (GUILayout.Button("Environment", GUILayout.Height(30)))

            {

                _debugType = DebugType.Environment;

            }

            GUI.contentColor = Color.white;

            GUILayout.EndHorizontal();

            #endregion

            #region console

            if (_debugType == DebugType.Console)

            {

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("Clear"))

                {

                    _logInformations.Clear();

                    _fatalLogCount = 0;

                    _warningLogCount = 0;

                    _errorLogCount = 0;

                    _infoLogCount = 0;

                    _currentLogIndex = -1;

                    _fpsColor = Color.white;

                }

                GUI.contentColor = (_showInfoLog ? Color.white : Color.gray);

                _showInfoLog = GUILayout.Toggle(_showInfoLog, "Info [" + _infoLogCount + "]");

                GUI.contentColor = (_showWarningLog ? Color.white : Color.gray);

                _showWarningLog = GUILayout.Toggle(_showWarningLog, "Warning [" + _warningLogCount + "]");

                GUI.contentColor = (_showErrorLog ? Color.white : Color.gray);

                _showErrorLog = GUILayout.Toggle(_showErrorLog, "Error [" + _errorLogCount + "]");

                GUI.contentColor = (_showFatalLog ? Color.white : Color.gray);

                _showFatalLog = GUILayout.Toggle(_showFatalLog, "Fatal [" + _fatalLogCount + "]");

                GUI.contentColor = Color.white;

                GUILayout.EndHorizontal();

                _scrollLogView = GUILayout.BeginScrollView(_scrollLogView, "Box", GUILayout.Height(165));

                for (int i = 0; i < _logInformations.Count; i++)

                {

                    bool show = false;

                    Color color = Color.white;

                    switch (_logInformations[i].type)

                    {

                        case "Fatal":

                            show = _showFatalLog;

                            color = Color.red;

                            break;

                        case "Error":

                            show = _showErrorLog;

                            color = Color.red;

                            break;

                        case "Info":

                            show = _showInfoLog;

                            color = Color.white;

                            break;

                        case "Warning":

                            show = _showWarningLog;

                            color = Color.yellow;

                            break;

                        default:

                            break;

                    }

                    if (show)

                    {

                        GUILayout.BeginHorizontal();

                        if (GUILayout.Toggle(_currentLogIndex == i, ""))

                        {

                            _currentLogIndex = i;

                        }

                        GUI.contentColor = color;

                        GUILayout.Label("[" + _logInformations[i].type + "] ");

                        GUILayout.Label("[" + _logInformations[i].time + "] ");

                        GUILayout.Label(_logInformations[i].message);

                        GUILayout.FlexibleSpace();

                        GUI.contentColor = Color.white;

                        GUILayout.EndHorizontal();

                    }

                }

                GUILayout.EndScrollView();

                _scrollCurrentLogView = GUILayout.BeginScrollView(_scrollCurrentLogView, "Box", GUILayout.Height(100));

                if (_currentLogIndex != -1)

                {

                    GUILayout.Label(_logInformations[_currentLogIndex].message + "\r\n\r\n" + _logInformations[_currentLogIndex].stackTrace);

                }

                GUILayout.EndScrollView();

            }

            #endregion

            #region memory

            else if (_debugType == DebugType.Memory)

            {

                GUILayout.BeginHorizontal();

                GUILayout.Label("Memory Information");

                GUILayout.EndHorizontal();

                GUILayout.BeginVertical("Box");

#if UNITY_5

            GUILayout.Label("总内存：" + Profiler.GetTotalReservedMemory() / 1000000 + "MB");

            GUILayout.Label("已占用内存：" + Profiler.GetTotalAllocatedMemory() / 1000000 + "MB");

            GUILayout.Label("空闲中内存：" + Profiler.GetTotalUnusedReservedMemory() / 1000000 + "MB");

            GUILayout.Label("总Mono堆内存：" + Profiler.GetMonoHeapSize() / 1000000 + "MB");

            GUILayout.Label("已占用Mono堆内存：" + Profiler.GetMonoUsedSize() / 1000000 + "MB");

#endif

#if UNITY_7

            GUILayout.Label("总内存：" + Profiler.GetTotalReservedMemoryLong() / 1000000 + "MB");

            GUILayout.Label("已占用内存：" + Profiler.GetTotalAllocatedMemoryLong() / 1000000 + "MB");

            GUILayout.Label("空闲中内存：" + Profiler.GetTotalUnusedReservedMemoryLong() / 1000000 + "MB");

            GUILayout.Label("总Mono堆内存：" + Profiler.GetMonoHeapSizeLong() / 1000000 + "MB");

            GUILayout.Label("已占用Mono堆内存：" + Profiler.GetMonoUsedSizeLong() / 1000000 + "MB");

#endif

                GUILayout.EndVertical();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("卸载未使用的资源"))

                {

                    Resources.UnloadUnusedAssets();

                }

                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("使用GC垃圾回收"))

                {

                    GC.Collect();

                }

                GUILayout.EndHorizontal();

            }

            #endregion

            #region system

            else if (_debugType == DebugType.System)

            {

                GUILayout.BeginHorizontal();

                GUILayout.Label("System Information");

                GUILayout.EndHorizontal();

                _scrollSystemView = GUILayout.BeginScrollView(_scrollSystemView, "Box");

                GUILayout.Label("操作系统：" + SystemInfo.operatingSystem);

                GUILayout.Label("系统内存：" + SystemInfo.systemMemorySize + "MB");

                GUILayout.Label("处理器：" + SystemInfo.processorType);

                GUILayout.Label("处理器数量：" + SystemInfo.processorCount);

                GUILayout.Label("显卡：" + SystemInfo.graphicsDeviceName);

                GUILayout.Label("显卡类型：" + SystemInfo.graphicsDeviceType);

                GUILayout.Label("显存：" + SystemInfo.graphicsMemorySize + "MB");

                GUILayout.Label("显卡标识：" + SystemInfo.graphicsDeviceID);

                GUILayout.Label("显卡供应商：" + SystemInfo.graphicsDeviceVendor);

                GUILayout.Label("显卡供应商标识码：" + SystemInfo.graphicsDeviceVendorID);

                GUILayout.Label("设备模式：" + SystemInfo.deviceModel);

                GUILayout.Label("设备名称：" + SystemInfo.deviceName);

                GUILayout.Label("设备类型：" + SystemInfo.deviceType);

                GUILayout.Label("设备标识：" + SystemInfo.deviceUniqueIdentifier);

                GUILayout.EndScrollView();

            }

            #endregion

            #region screen

            else if (_debugType == DebugType.Screen)

            {

                GUILayout.BeginHorizontal();

                GUILayout.Label("Screen Information");

                GUILayout.EndHorizontal();

                GUILayout.BeginVertical("Box");

                GUILayout.Label("DPI：" + Screen.dpi);

                GUILayout.Label("分辨率：" + Screen.currentResolution.ToString());

                GUILayout.EndVertical();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("全屏"))

                {

                    Screen.SetResolution(Screen.currentResolution.width, Screen.currentResolution.height, !Screen.fullScreen);

                }

                GUILayout.EndHorizontal();

            }

            #endregion

            #region Quality

            else if (_debugType == DebugType.Quality)

            {

                GUILayout.BeginHorizontal();

                GUILayout.Label("Quality Information");

                GUILayout.EndHorizontal();

                GUILayout.BeginVertical("Box");

                string value = "";

                if (QualitySettings.GetQualityLevel() == 0)

                {

                    value = " [最低]";

                }

                else if (QualitySettings.GetQualityLevel() == QualitySettings.names.Length - 1)

                {

                    value = " [最高]";

                }

                GUILayout.Label("图形质量：" + QualitySettings.names[QualitySettings.GetQualityLevel()] + value);

                GUILayout.EndVertical();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("降低一级图形质量"))

                {

                    QualitySettings.DecreaseLevel();

                }

                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("提升一级图形质量"))

                {

                    QualitySettings.IncreaseLevel();

                }

                GUILayout.EndHorizontal();

            }

            #endregion

            #region Environment

            else if (_debugType == DebugType.Environment)

            {

                GUILayout.BeginHorizontal();

                GUILayout.Label("Environment Information");

                GUILayout.EndHorizontal();

                GUILayout.BeginVertical("Box");

                GUILayout.Label("项目名称：" + Application.productName);

#if UNITY_5

            GUILayout.Label("项目ID：" + Application.bundleIdentifier);

#endif

#if UNITY_7

            GUILayout.Label("项目ID：" + Application.identifier);

#endif

                GUILayout.Label("项目版本：" + Application.version);

                GUILayout.Label("Unity版本：" + Application.unityVersion);

                GUILayout.Label("公司名称：" + Application.companyName);

                GUILayout.EndVertical();

                GUILayout.BeginHorizontal();

                if (GUILayout.Button("退出程序"))

                {

                    Application.Quit();

                }

                GUILayout.EndHorizontal();

            }

            #endregion

        }

        private void ShrinkGUIWindow(int windowId)

        {

            GUI.DragWindow(new Rect(0, 0, 10000, 20));

            GUI.contentColor = _fpsColor;

            if (GUILayout.Button("FPS:" + _fps, GUILayout.Width(80), GUILayout.Height(30)))

            {

                _expansion = true;

                _windowRect.width = 600;

                _windowRect.height = 360;

            }

            GUI.contentColor = Color.white;

        }

    }

    public struct LogData

    {

        public string time;

        public string type;

        public string message;

        public string stackTrace;

    }

    public enum DebugType

    {

        Console,

        Memory,

        System,

        Screen,

        Quality,

        Environment

    }
}
